package cn.lang.file;

import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.function.BiFunction;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Markdown文件处理器
 *
 * @author Lang
 * @date 2022/09/23
 */
@Component
public class MarkDownHandler {

    private Logger log = LoggerFactory.getLogger(MarkDownHandler.class);

    public static final String FILE_TYPE_MD = ".md";

    /**
     * markdown 相对定位图片地址 替换成oss地址
     *
     * @param dir       要处理markdown文件所在目录 eg E://markdown/lang
     * @param removeDir 上传oss时会根据image所在磁盘路径存入oss removeDir为移除目录的部分   eg removeDir: E://markdown  图片E://markdown/lang/a.png 存储oss时即 http://xxx.xx/lang/a.png
     * @param function  图片上传处理函数
     */
    public void replaceImageOss(String dir, String removeDir, BiFunction<File, String, String> function) {
        Path path = Paths.get(dir);
        try {
            Files.walkFileTree(path, new FileVisitor<Path>() {
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    log.info("读取到目录：{}", dir.getFileName());
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
                    log.info("读取到文件：{}", path.getFileName());
                    if (!StrUtil.endWith(path.getFileName().toString(), FILE_TYPE_MD, true)) {
                        return FileVisitResult.CONTINUE;
                    }
                    File mdFile = path.toFile();
                    String mdPath = mdFile.getPath();
                    String[] split = mdPath.split("\\\\");
                    //md文件所在目录
                    String mdDir = mdPath.replace(split[split.length - 1], "");
                    FileReader fileReader = new FileReader(mdFile);
                    String mdContent = fileReader.readString();
                    String reg = "!\\[.*\\]\\(([^http].*[\\.png|\\.jpg|\\.jepg])\\)";
                    Matcher m = Pattern.compile(reg).matcher(mdContent);
                    while (m.find()) {
                        String imgAddr = m.group(1);
                        //找到图片文件所在路径
                        String imgAbsoluteAddr = mdDir + imgAddr;
                        log.info("文件所在磁盘绝对路径：{}", imgAbsoluteAddr);
                        File imgFile = new File(imgAbsoluteAddr);
                        String url = function.apply(imgFile, imgAddr.replace(removeDir, "").replace("\\", "/"));
                        log.info("文件上传OSS地址：{}", url);
                        if (StrUtil.isNotBlank(url)) {
                            mdContent = mdContent.replace(imgAddr, url);
                        } else {
                            log.error("图片替换失败 markdown文件为：{}，图片为：{}", mdPath, imgAbsoluteAddr);
                        }
                    }
                    //替换后重新写入文件
                    FileWriter writer = new FileWriter(mdFile);
                    writer.write(mdContent);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}
